package cn.z2huo.demo.data.generate.database.user;

import cn.hutool.core.date.DateTime;
import cn.hutool.core.util.RandomUtil;
import cn.z2huo.core.util.IdUtils;
import cn.z2huo.demo.data.generate.database.enums.company.ComFlagEnum;
import cn.z2huo.demo.data.generate.database.enums.company.ComLevelEnum;
import cn.z2huo.demo.data.generate.database.enums.user.RoamingTypeEnum;
import cn.z2huo.demo.data.generate.database.enums.user.SvrScopeEnum;
import cn.z2huo.demo.data.generate.database.enums.user.UserTypeEnum;
import cn.z2huo.demo.mapper.ccip.CcipUserMapper;
import cn.z2huo.demo.mapper.company.CompanyMapper;
import cn.z2huo.demo.model.dataobject.ccip.CcipUserDO;
import cn.z2huo.demo.model.dataobject.company.CompanyDO;
import com.baomidou.mybatisplus.core.batch.MybatisBatch;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import jakarta.annotation.Nonnull;
import jakarta.annotation.PostConstruct;
import lombok.RequiredArgsConstructor;
import org.apache.ibatis.session.SqlSessionFactory;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Component;

import java.util.*;

/**
 * <p>生成用户数据，没有区分财险，没有设置用户的省公司
 *
 * @author z2huo
 */
@Component
@RequiredArgsConstructor
@Deprecated
public class UserDataGenerator {

    /**
     * 需要生成数据的默认数据量
     */
    private static final int GENERATE_DATA_COUNT = 1_000_000;

    private static final List<String> SVR_SCOPE_VALUE_LIST = Arrays.stream(SvrScopeEnum.values()).map(SvrScopeEnum::getValue).toList();

    private static final List<String> USER_TYPE_VALUE_LIST = Arrays.stream(UserTypeEnum.values()).map(UserTypeEnum::getValue).toList();

    private static final List<String> ROAMIN_TYPE_VALUE_LIST = Arrays.stream(RoamingTypeEnum.values()).map(RoamingTypeEnum::getValue).toList();

    private final CcipUserMapper userMapper;

    private final CompanyMapper companyMapper;

    private final ThreadPoolTaskExecutor executor;

    private final SqlSessionFactory sqlSessionFactory;

    private final Map<SvrScopeEnum, List<String>> svrScopeCompanyCodeList = new HashMap<>(SvrScopeEnum.values().length);

    @PostConstruct
    public void init() {
        for (SvrScopeEnum svrScopeEnum : SvrScopeEnum.values()) {
            svrScopeCompanyCodeList.computeIfAbsent(svrScopeEnum, scopeEnum -> {
                LambdaQueryWrapper<CompanyDO> queryWrapper = Wrappers.lambdaQuery(CompanyDO.class);
                queryWrapper.select(CompanyDO::getComCode);
                // 部门
                queryWrapper.eq(CompanyDO::getComFlag, ComFlagEnum.ORGANIZATION.getValue());
                // 子公司
                queryWrapper.eq(CompanyDO::getInsurerCode, scopeEnum.getValue());
                // 机构级别
                queryWrapper.in(CompanyDO::getComLevel,
                        List.of(ComLevelEnum.HEAD_QUARTERS, ComLevelEnum.PROVINCIAL_COMPANY,
                                ComLevelEnum.CITY_COMPANY, ComLevelEnum.COUNTY_BRANCH)
                                .stream().map(ComLevelEnum::getValue).toArray()
                );
                return companyMapper.selectList(queryWrapper).stream().map(CompanyDO::getComCode).toList();
            });
        }
    }

    public void generate(int dataCount,
                         @Nonnull SvrScopeEnum svrScopeEnum) {

        for (int i = 0; i < dataCount; i++) {
            CcipUserDO ccipUserDO = generateUserDO(svrScopeEnum);
            userMapper.insert(ccipUserDO);
        }
    }

    public void generateBatchInsert(int dataCount,
                                    int batchSize,
                                    @Nonnull SvrScopeEnum svrScopeEnum) {

        int batchCount = dataCount % batchSize == 0 ? dataCount / batchSize : dataCount / batchSize + 1;
//        int batchCount = dataCount / batchSize;

        for (int i = 0; i < batchCount; i++) {
            int size = i == batchCount - 1 ? dataCount % batchSize : batchSize;
            List<CcipUserDO> userDOList = new ArrayList<>(size);
            for (int j = 0; j < size; j++) {
                userDOList.add(generateUserDO(svrScopeEnum));
            }
            this.batchInsert(userDOList);
        }
    }

    private void batchInsert(List<CcipUserDO> userDOList) {
        MybatisBatch<CcipUserDO> ccipUserDOMybatisBatch = new MybatisBatch<CcipUserDO>(sqlSessionFactory, userDOList);
        MybatisBatch.Method<CcipUserDO> method = new MybatisBatch.Method<>(CcipUserMapper.class);
        ccipUserDOMybatisBatch.execute(method.insert());
    }

    private CcipUserDO generateUserDO(@Nonnull SvrScopeEnum svrScopeEnum) {
        CcipUserDO ccipUserDO = new CcipUserDO();
        ccipUserDO.setId(IdUtils.nextId());
        ccipUserDO.setSvrScope(svrScopeEnum.getValue());
        ccipUserDO.setUserType(RandomUtil.randomEle(USER_TYPE_VALUE_LIST));
        ccipUserDO.setRoamingType(RandomUtil.randomEle(ROAMIN_TYPE_VALUE_LIST));

        ccipUserDO.setGroupUserCode(RandomUtil.randomNumbers(10));
        int nameLength = RandomUtil.randomInt(2, 4, true, true);
        StringBuilder sb = new StringBuilder();
        for (int j = 0; j < nameLength; j++) {
            sb.append(RandomUtil.randomChinese());
        }
        ccipUserDO.setUserName(sb.toString());

        List<String> companyCodeList = svrScopeCompanyCodeList.get(svrScopeEnum);
        String comCode = RandomUtil.randomEle(companyCodeList);
        ccipUserDO.setComCode(comCode);
        ccipUserDO.setPComCode(comCode);

        String userCode = RandomUtil.randomNumbers(8);
        ccipUserDO.setNewUserCode(userCode);
        ccipUserDO.setOldUserCode(userCode);

        ccipUserDO.setValidStatus("1");
        ccipUserDO.setRemark(RandomUtil.randomString(RandomUtil.randomInt(20, 80)));

        ccipUserDO.setSysSource(RandomUtil.randomEle(List.of("1", "2", "3")));

        ccipUserDO.setPGradeName(RandomUtil.randomString(RandomUtil.randomInt(10, 30)));
        DateTime dateTime = RandomUtil.randomDay(-3650, 0);
        ccipUserDO.setPGradeDate(dateTime.toLocalDateTime().toLocalDate());

        ccipUserDO.setUserSort("1");
        ccipUserDO.setCrossUserFlag("0");
        ccipUserDO.setRoamingStatus("0");

        ccipUserDO.setValidEndDate(RandomUtil.randomDay(365, 3650).toLocalDateTime().toLocalDate());

        ccipUserDO.setFlag("0");

        return ccipUserDO;
    }

}
